/**
 * ...
 * >author		João Vítor de Souza
 */

package com.cupcakeengine.core 
{
	
	import com.cupcakeengine.CKEngine;
	import com.cupcakeengine.data.RegisterPoint;	
	import com.cupcakeengine.display.BitmapObject;	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;	
	import flash.events.EventDispatcher;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;

	public class BitmapFactory extends EventDispatcher 
	{
		// ___________________________________________________________________ CONSTANTS
		
		// ___________________________________________________________________ CLASS PROPERTIES
		
		private var _dBitmapData						: Dictionary;		
		private var _currentVector						: Vector.<BitmapData>;	
		private var _label								: String;
		
		// ___________________________________________________________________ INSTANCE PROPERTIES
		
		private static var _instance	: BitmapFactory;
		
		// ___________________________________________________________________ GETTERS AND SETTERS
		
		// ___________________________________________________________________ CONSTRUCTOR
		
		public function BitmapFactory (singleton:SingletonObligate) {}
		
		// ___________________________________________________________________ PUBLIC METHODS
		
		public static function getInstance () : BitmapFactory
		{
			if (!BitmapFactory._instance) BitmapFactory._instance = new BitmapFactory(new SingletonObligate());
			return BitmapFactory(BitmapFactory._instance);
		}
		
		public function getBitmapObject(display:DisplayObject, align:String, isTransparent:Boolean, bitmapDataObject:Object, bitmapObject:Object):BitmapObject
		{
			bitmapDataObject = getBitmapDataObject(display, align, bitmapDataObject);
			
			if (bitmapObject == null) bitmapObject = new Object();
			if (bitmapObject.pixelSnapping == null) bitmapObject.pixelSnapping = "auto";
			if (bitmapObject.smoothing  == null) bitmapObject.smoothing = true;
			
			var rectangle:Rectangle = display.getBounds(CKEngine.root);			
			var bitmapData:BitmapData = getBitmapDataVector(display, bitmapDataObject, rectangle)					
			
			var object:BitmapObject = new BitmapObject(bitmapData, rectangle, _dBitmapData, _currentVector, _label);
			
			_dBitmapData = null;			
			_currentVector = null;
			_label = null;
			
			return object;
		}
		
		//public function getBitmap(display:DisplayObject, align:String, bitmapDataObject:Object, bitmapObject:Object):DisplayObject
		//{			
			//bitmapDataObject = getBitmapDataObject(display, align, bitmapDataObject);
			//
			//var bitmapData:BitmapData = getBitmapData(display, bitmapDataObject);
			//
			//return new Bitmap(bitmapData, bitmapObject.pixelSnapping, bitmapObject.smoothing);
		//}		
		
		// ___________________________________________________________________ PRIVATE METHODS		
		
		private function getBitmapDataVector(display:DisplayObject, bitmapDataObject:Object, rectangle:Rectangle):BitmapData
		{		
			var vBitmapData:Vector.<BitmapData> = new Vector.<BitmapData>;
			var bitmapData:BitmapData;
			if (display is MovieClip) {
				_dBitmapData = new Dictionary();				
				
				var len:int = MovieClip(display).totalFrames;
				var label:String;
				var mc:MovieClip = display as MovieClip;				
				
				for (var i:int = 0; i < len; i++) {
					mc.gotoAndStop(i + 1);					
					label = mc.currentLabel;
					bitmapData = getBitmapData(mc, bitmapDataObject, rectangle);
					if (_dBitmapData[label] == null) {
						_dBitmapData[label] = new Vector.<BitmapData>;
						vBitmapData = _dBitmapData[label];
						if (_currentVector == null) {
							_currentVector = _dBitmapData[label];
							_label = label;
						}
					}
					
					vBitmapData.push(bitmapData);
				}
			} else {
				return getBitmapData(display, bitmapDataObject, rectangle);
			}
			
			return _currentVector[0];
		}
		
		private function getBitmapData(display:DisplayObject, bitmapDataObject:Object, rectangle:Rectangle):BitmapData
		{
			var bitmapData:BitmapData = new BitmapData(rectangle.width, rectangle.height, bitmapDataObject.transparent, bitmapDataObject.fillColor);
			bitmapData.draw(display, bitmapDataObject.matrix, bitmapDataObject.colorTransform, bitmapDataObject.blendMode, bitmapDataObject.clipRect, bitmapDataObject.smoothing);	
			return bitmapData;
		}
		
		private function getBitmapDataObject(display:DisplayObject, align:String, bitmapDataObject:Object):Object
		{
			if (bitmapDataObject == null) bitmapDataObject = new Object();
			if (bitmapDataObject.transparent == null) bitmapDataObject.transparent = true;
			//if (bitmapDataObject.fillColor == null) bitmapDataObject.fillColor = uint(4294967295);	
			if (bitmapDataObject.fillColor == null) bitmapDataObject.fillColor = uint(0);			
			
			bitmapDataObject.matrix = getBitmapDataMatrix(display, align);	
			
			return bitmapDataObject;
		}
		
		private function getBitmapDataMatrix(display:DisplayObject, align:String):Matrix
		{
			switch(align) {
				case RegisterPoint.BOTTOM: 			return new Matrix(1, 0, 0, 1, display.width >> 1, display.height);
				case RegisterPoint.BOTTOM_LEFT: 	return new Matrix(1, 0, 0, 1, 0, display.height);
				case RegisterPoint.BOTTOM_RIGHT: 	return new Matrix(1, 0, 0, 1, display.width, display.height);
				case RegisterPoint.CENTER: 			return new Matrix(1, 0, 0, 1, display.width >> 1, display.height >> 1);
				case RegisterPoint.LEFT: 			return new Matrix(1, 0, 0, 1, 0, display.height >> 1);
				case RegisterPoint.RIGHT: 			return new Matrix(1, 0, 0, 1, display.width, display.height >> 1);
				case RegisterPoint.TOP: 			return new Matrix(1, 0, 0, 1, display.width >> 1, 0);
				case RegisterPoint.TOP_LEFT:		return new Matrix(1, 0, 0, 1, 0, 0);
				case RegisterPoint.TOP_RIGHT:		return new Matrix(1, 0, 0, 1, display.width, 0);
			}
			
			return null;
		}
		
		// ___________________________________________________________________ EVENTS
	}
}

class SingletonObligate {}
